/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 simple_adv_object_image.h

	$Header: /heroes4/simple_adv_object_image.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( SIMPLE_ADV_OBJECT_IMAGE_H_INCLUDED )
#define SIMPLE_ADV_OBJECT_IMAGE_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning( disable: 4786 ) // Disable the ever so helpful "identifier was truncated to '255' characters" warning

#include "adv_object_image.h"
#include "image_sequence.h"
#include "sized_int_types.h"

// ------------------------------------------------------------------------------
// t_simple_adv_object_image_base class template
// ------------------------------------------------------------------------------

template < typename t_base, typename t_derived, typename t_sequence >
class t_simple_adv_object_image_base : public t_base
{
public:
	// Constructors
	t_simple_adv_object_image_base();
	template < typename t_other_base, typename t_other_derived, typename t_other_sequence >
	t_simple_adv_object_image_base( t_simple_adv_object_image_base< t_other_base, t_other_derived, t_other_sequence > const & other )
		:	m_sequence( other.m_sequence )
	{
	}
	t_simple_adv_object_image_base( t_simple_adv_object_image_base const & other );

	// Member functions
	virtual int get_frame_count() const;
	virtual t_screen_point get_offset() const;
	virtual t_screen_rect get_rect() const;
	virtual t_screen_rect get_rect( int frame_num ) const;
	virtual t_uint16	  get_sequence_type() const;
	virtual t_screen_rect get_shadow_rect() const;
	virtual t_screen_rect get_shadow_rect( int frame_num ) const;
	virtual bool hit_test( int frame_num, t_screen_point const & point ) const;
	virtual	void toggle_base_frame_draw(bool val);

	void set_offset( t_screen_point const & new_offset );

	void set_sequence_type(t_uint16 seq_type);
	void set_frame_base(t_uint16 frame_num);
	void set_shadow_base(t_uint16 frame_num);

protected:
	// Member functions
	virtual void on_rect_changed( t_screen_rect const & old_rect, t_screen_rect const & new_rect );

	// The following section should be private because instatiations of
	// t_simple adv_object_image_base need access to the private members of
	// any other instatiation and friend declaration templates do not work
	// under MSVC++ 6.0.
//private:
public:

	friend t_derived;

	// Data members
	t_sequence	m_sequence;
};

template < typename t_base, typename t_derived, typename t_sequence >
inline t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::t_simple_adv_object_image_base()
{
}

template < typename t_base, typename t_derived, typename t_sequence >
inline t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::t_simple_adv_object_image_base( t_simple_adv_object_image_base const & other )
	:	m_sequence( other.m_sequence )
{
}

template < typename t_base, typename t_derived, typename t_sequence >
int t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_frame_count() const
{
	return m_sequence.get_frame_count();
}

template < typename t_base, typename t_derived, typename t_sequence >
t_screen_point t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_offset() const
{
	return m_sequence.get_offset();
}

template < typename t_base, typename t_derived, typename t_sequence >
t_screen_rect t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_rect() const
{
	return m_sequence.get_rect();
}

template < typename t_base, typename t_derived, typename t_sequence >
t_uint16 t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_sequence_type() const
{
	return m_sequence.get_sequence_type();
}

template < typename t_base, typename t_derived, typename t_sequence >
t_screen_rect t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_rect( int frame_num ) const
{
	return m_sequence.get_rect( frame_num );
}

template < typename t_base, typename t_derived, typename t_sequence >
t_screen_rect t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_shadow_rect() const
{
	return m_sequence.get_shadow_rect();
}

template < typename t_base, typename t_derived, typename t_sequence >
t_screen_rect t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::get_shadow_rect( int frame_num ) const
{
	return m_sequence.get_shadow_rect( frame_num );
}

template < typename t_base, typename t_derived, typename t_sequence >
bool t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::hit_test( int frame_num, t_screen_point const & point ) const
{
	return m_sequence.hit_test( frame_num, point );
}

template < typename t_base, typename t_derived, typename t_sequence >
void t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::toggle_base_frame_draw(bool val)
{
	m_sequence.toggle_base_frame_draw(val);
}

template < typename t_base, typename t_derived, typename t_sequence >
void t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::set_offset( t_screen_point const & new_offset )
{
	t_screen_rect old_rect = m_sequence.get_rect();
	m_sequence.set_offset( new_offset );
	t_screen_rect new_rect = m_sequence.get_rect();
	if ( new_rect != old_rect )
		on_rect_changed( old_rect, new_rect );
}

template < typename t_base, typename t_derived, typename t_sequence >
void t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::set_sequence_type(t_uint16 seq_type)
{
	m_sequence.set_sequence_type(seq_type);
}

template < typename t_base, typename t_derived, typename t_sequence >
void t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::set_frame_base(t_uint16 frame_num)
{
	m_sequence.set_frame_base(frame_num);
}

template < typename t_base, typename t_derived, typename t_sequence >
void t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::set_shadow_base(t_uint16 frame_num)
{
	m_sequence.set_shadow_base(frame_num);
}

template < typename t_base, typename t_derived, typename t_sequence >
void t_simple_adv_object_image_base< t_base, t_derived, t_sequence >::on_rect_changed( t_screen_rect const & old_rect, t_screen_rect const & new_rect )
{
}

// ------------------------------------------------------------------------------
// t_simple_adv_object_image_24 class
// ------------------------------------------------------------------------------

class t_simple_adv_object_image_24 : public t_simple_adv_object_image_base< t_adv_object_image_24, t_simple_adv_object_image_24, t_image_sequence_24 >
{
public:
	// Member functions
	virtual void get_frames( t_bitmap_group_24 & bitmap_group ) const;
	bool set_frames( t_bitmap_group_24 const & bitmap_group );
	bool set_frames( t_bitmap_group_24 const & bitmap_group , t_screen_point const & offset);
	bool read( std::streambuf & stream );
	bool read_version( std::streambuf & stream, int version );
	bool write( std::streambuf & stream ) const;
};

// ------------------------------------------------------------------------------
// t_simple_adv_object_image class
// ------------------------------------------------------------------------------

class t_simple_adv_object_image : public t_simple_adv_object_image_base< t_adv_object_image, t_simple_adv_object_image, t_image_sequence >
{
public:
	// Constructor
	t_simple_adv_object_image();
	t_simple_adv_object_image( t_simple_adv_object_image_24 const & other );

	// Member functions
	virtual void	draw_to(
						int						frame_num,
						t_screen_rect const &	source_rect,
						t_abstract_bitmap16 &	dest,
						t_screen_point const &	dest_point,
						int						alpha = 15 ) const;
	virtual void	draw_to(
						int						frame_num,
						t_abstract_bitmap16 &	dest,
						t_screen_point const &	dest_point ) const;
	virtual void	draw_shadow_to(
						int						frame_num,
						t_screen_rect const &	source_rect,
						t_abstract_bitmap16 &	dest,
						t_screen_point const &	dest_point ) const;
	virtual void	draw_shadow_to(
						int						frame_num,
						t_abstract_bitmap16 &	dest,
						t_screen_point const &	dest_point ) const;
};

inline t_simple_adv_object_image::t_simple_adv_object_image()
{
}

inline t_simple_adv_object_image::t_simple_adv_object_image( t_simple_adv_object_image_24 const & other )
	:	t_simple_adv_object_image_base< t_adv_object_image, t_simple_adv_object_image, t_image_sequence >( other )
{
}

#endif // !defined( SIMPLE_ADV_OBJECT_IMAGE_H_INCLUDED )
